package com.taobang.appgroups;

import java.util.ArrayList;
import java.util.Vector;

import org.jgroups.Address;
import org.jgroups.Channel;
import org.jgroups.ChannelFactory;
import org.jgroups.JChannelFactory;
import org.jgroups.View;
import org.jgroups.blocks.ReplicatedHashMap;

public class AppGroupsMain {

	/**
	 * Application Group Name
	 */
	private static final String groupname = "taobang";

	/**
	 * Application Group Props
	 */
	private static final String props = "UDP(mcast_addr=228.8.8.8;mcast_port=45566;ip_ttl=32;"
			+ "mcast_send_buf_size=150000;mcast_recv_buf_size=80000):"
			+ "PING(timeout=2000;num_initial_members=3):"
			+ "MERGE2(min_interval=5000;max_interval=10000):"
			+ "FD_SOCK:"
			+ "VERIFY_SUSPECT(timeout=1500):"
			+ "pbcast.NAKACK(gc_lag=50;retransmit_timeout=300,600,1200,2400,4800):"
			+ "UNICAST(timeout=5000):"
			+ "pbcast.STABLE(desired_avg_gossip=20000):"
			+ "FRAG(frag_size=4096;down_thread=false;up_thread=false):"
			+ "pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;"
			+ "shun=false;print_local_addr=true):" + "pbcast.STATE_TRANSFER";

	private ReplicatedHashMap<String, String> map;
	private Channel channel;
	
	/**
	 * connect the Application groups using the default group name and properties.
	 * @return 0 - success; -1 - false;
	 */
	public int connectGroup() {
		int ret = 0;

		try {
			// Connect Group
			ChannelFactory factory = new JChannelFactory(props);
			channel = factory.createChannel();
			map = new ReplicatedHashMap<String, String>(channel, 0);
			channel.connect(groupname);
			map.start(0);

		} catch (Exception e) {
			ret = -1;
		}

		return ret;
	}

	public void disConnectGroup() {
		if (channel != null)
			channel.disconnect();

		if (map != null)
			map.stop();
	}

	/**
	 * List the application groups members
	 * @return the members list
	 */
	public ArrayList<String> list() {
		View v = channel.getView();
		if (v == null) {
			return null;
		}

		Vector<Address> a = v.getMembers();

		if (a == null) {
			return null;
		}
		
		ArrayList<String> res = new ArrayList<String>();

		for (Address item : a) {
			if (map.containsKey(item.toString())) {
				res.add(item.toString());
			}
		}
		
		return res;
	}
	
	/**
	 * get the current application's address string. 
	 * @return
	 */
	public String current() {
		return channel.getLocalAddress().toString();
	}
	
	/**
	 * Get the application's info which is set by user
	 * @param name
	 * @return
	 */
	public String get(String name) {
		if( map.containsKey(name))
			return map.get(name);
		else
			return null;
	}

	/**
	 * set the application's info.
	 * @param name 
	 * @param value
	 */
	public void set(String name, String value ) {
		if (value == null || value == null )
			throw new NullPointerException();

		map.put(name, value);
	}
	

	public static void main(String[] args) {
		AppGroupsMain t = new AppGroupsMain();
		t.connectGroup();
		t.disConnectGroup();
	}
}